package br.edu.ufcg.unknown.lexico;

import java.io.IOException;

import br.edu.ufcg.unknown.exception.AnalisadorLexicoUnknownRuntimeException;
import br.edu.ufcg.unknown.exception.UnknownException;

public class AnalisadorLexicoTest extends UnknownTest {

	private AnalisadorLexico al = null;

	private String caracteresInvalidos = ",{}?";

	// private File palavrasReservadas = new File("tokens.txt");

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		al = new AnalisadorLexico();
	}

	public void testGetProxToken() throws UnknownException {
		Token token = null;

		al = new AnalisadorLexico("");
		token = al.getProxToken();
		assertNull(token);

		al = new AnalisadorLexico("	END;\nEND");
		token = al.getProxToken();
		assertEquals("END", token.getLexema());
		assertEquals(1, token.getLinha());
		assertEquals(2, token.getColuna());
		token = al.getProxToken();
		assertEquals(";", token.getLexema());
		assertEquals(1, token.getLinha());
		assertEquals(5, token.getColuna());
		token = al.getProxToken();
		assertEquals("END", token.getLexema());
		assertEquals(2, token.getLinha());
		assertEquals(1, token.getColuna());
		token = al.getProxToken();
		assertNull(token);

	}

	public void testGetProxTokenLancarErro() throws UnknownException {
		AnalisadorLexicoUnknownRuntimeException exp = null;

		// 1o. Teste
		al = new AnalisadorLexico("?");
		exp = new AnalisadorLexicoUnknownRuntimeException(ErrosAnalisadorLexico.SIMBOLO_INVALIDO, '?');
		try {
			al.getProxToken();
			fail("Erro! Era pra ter sido lancada uma exceção de caractere inválido");
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(exp, e);
		}
		
		// 2o. Teste
		al = new AnalisadorLexico("c :== 'hello;\n}\nEND");
		exp = new AnalisadorLexicoUnknownRuntimeException(ErrosAnalisadorLexico.CADEIA_NAO_FECHADA,  (Token)null);
		try {
			assertNotNull(al.getProxToken());
			assertNotNull(al.getProxToken());
			assertNotNull(al.getProxToken());
			al.getProxToken();
			fail("Erro! Era pra ter sido lancada uma exceção de caractere inválido");
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(exp, e);
		}
		
	}

	public void testEhInicioIdentificador() {
		for (char caractere = 'a'; caractere < 'z'; caractere++) {
			assertTrue(al.ehInicioIdentificador(caractere));
		}
		for (char caractere = 'A'; caractere < 'Z'; caractere++) {
			assertTrue(al.ehInicioIdentificador(caractere));
		}
		assertTrue(al.ehInicioIdentificador('_'));
		for (char caractere = '0'; caractere < '9'; caractere++) {
			assertFalse(al.ehInicioIdentificador(caractere));
		}
		assertFalse(al.ehInicioIdentificador(' '));
		assertFalse(al.ehInicioIdentificador(';'));
	}

	public void testGetIdentificador() throws UnknownException {

		Token token = null;

		al = new AnalisadorLexico("");
		token = al.getIdentificador();
		assertNull(token);

		al = new AnalisadorLexico("asdf");
		token = al.getIdentificador();
		assertEquals("asdf", token.getLexema());

		al = new AnalisadorLexico("asdf ");
		token = al.getIdentificador();
		assertEquals("asdf", token.getLexema());

		al = new AnalisadorLexico("asdf0");
		token = al.getIdentificador();
		assertEquals("asdf0", token.getLexema());

		al = new AnalisadorLexico("asdf0asdf ");
		token = al.getIdentificador();
		assertEquals("asdf0asdf", token.getLexema());

		al = new AnalisadorLexico("asdf:");
		token = al.getIdentificador();
		assertEquals("asdf", token.getLexema());

		al = new AnalisadorLexico("asdf)");
		token = al.getIdentificador();
		assertEquals("asdf", token.getLexema());

		al = new AnalisadorLexico("asdf;");
		token = al.getIdentificador();
		assertEquals("asdf", token.getLexema());

		al = new AnalisadorLexico("asdf'");
		token = al.getIdentificador();
		assertEquals("asdf", token.getLexema());

		al = new AnalisadorLexico("IDADE_MAXIMA");
		token = al.getIdentificador();
		assertEquals("IDADE_MAXIMA", token.getLexema());

	}

	public void testGetIdentificadorComCaracteresInvalidos() throws UnknownException {

		Token token = null;

		al = new AnalisadorLexico("a" + caracteresInvalidos + "sdf");
		try {
			token = al.getIdentificador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("asdf", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}

		al = new AnalisadorLexico("a" + caracteresInvalidos + "sdf ");
		try {
			token = al.getIdentificador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("asdf", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}

		al = new AnalisadorLexico("a" + caracteresInvalidos + "sdf0");
		try {
			token = al.getIdentificador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("asdf0", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}

		al = new AnalisadorLexico("a" + caracteresInvalidos + "sdf0asdf ");
		try {
			token = al.getIdentificador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("asdf0asdf", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}

		al = new AnalisadorLexico("a" + caracteresInvalidos + "sdf:");
		try {
			token = al.getIdentificador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("asdf", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}

		al = new AnalisadorLexico("a" + caracteresInvalidos + "sdf)");
		try {
			token = al.getIdentificador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("asdf", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}

		al = new AnalisadorLexico("a" + caracteresInvalidos + "sdf;");
		try {
			token = al.getIdentificador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("asdf", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}

		al = new AnalisadorLexico("a" + caracteresInvalidos + "sdf'");
		try {
			token = al.getIdentificador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("asdf", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}
	}

	public void testGetIdentificadorLinhaEColunaDoToken() throws UnknownException {

		Token token = null;

		al = new AnalisadorLexico("asdf");
		token = al.getProxToken();
		assertTrue(token.ehIdentificador());
		assertEquals(1, token.getLinha());
		assertEquals(1, token.getColuna());

		al = new AnalisadorLexico(" asdf");
		token = al.getProxToken();
		assertTrue(token.ehIdentificador());
		assertEquals(1, token.getLinha());
		assertEquals(2, token.getColuna());

		al = new AnalisadorLexico("\nasdf");
		token = al.getProxToken();
		assertTrue(token.ehIdentificador());
		assertEquals(2, token.getLinha());
		assertEquals(1, token.getColuna());

		al = new AnalisadorLexico("\n asdf");
		token = al.getProxToken();
		assertTrue(token.ehIdentificador());
		assertEquals(2, token.getLinha());
		assertEquals(2, token.getColuna());
	}

	public void testEhInicioOperador() throws UnknownException {

		// Testar Operador seguido por espaço em branco
		al = new AnalisadorLexico("+ ");
		assertTrue(al.ehInicioOperador('+'));
		al = new AnalisadorLexico("- ");
		assertTrue(al.ehInicioOperador('-'));
		al = new AnalisadorLexico("* ");
		assertTrue(al.ehInicioOperador('*'));
		al = new AnalisadorLexico("/ ");
		assertTrue(al.ehInicioOperador('/'));
		al = new AnalisadorLexico("= ");
		assertTrue(al.ehInicioOperador('='));
		al = new AnalisadorLexico("> ");
		assertTrue(al.ehInicioOperador('>'));
		al = new AnalisadorLexico(">= ");
		assertTrue(al.ehInicioOperador('>'));
		al = new AnalisadorLexico("< ");
		assertTrue(al.ehInicioOperador('<'));
		al = new AnalisadorLexico("<= ");
		assertTrue(al.ehInicioOperador('<'));
		al = new AnalisadorLexico("<> ");
		assertTrue(al.ehInicioOperador('<'));
		al = new AnalisadorLexico(": ");
		assertTrue(al.ehInicioOperador(':'));
		al = new AnalisadorLexico(":= ");
		assertTrue(al.ehInicioOperador(':'));

		// Testar Operador seguido por qualquer outro caractere válido ('Z')
		al = new AnalisadorLexico("+Z");
		assertTrue(al.ehInicioOperador('+'));
		al = new AnalisadorLexico("-Z");
		assertTrue(al.ehInicioOperador('-'));
		al = new AnalisadorLexico("*Z");
		assertTrue(al.ehInicioOperador('*'));
		al = new AnalisadorLexico("/Z");
		assertTrue(al.ehInicioOperador('/'));
		al = new AnalisadorLexico("=Z");
		assertTrue(al.ehInicioOperador('='));
		al = new AnalisadorLexico(">Z");
		assertTrue(al.ehInicioOperador('>'));
		al = new AnalisadorLexico(">=Z");
		assertTrue(al.ehInicioOperador('>'));
		al = new AnalisadorLexico("<Z");
		assertTrue(al.ehInicioOperador('<'));
		al = new AnalisadorLexico("<=Z");
		assertTrue(al.ehInicioOperador('<'));
		al = new AnalisadorLexico("<>Z");
		assertTrue(al.ehInicioOperador('<'));
		al = new AnalisadorLexico(":Z");
		assertTrue(al.ehInicioOperador(':'));
		al = new AnalisadorLexico(":=Z");
		assertTrue(al.ehInicioOperador(':'));

		assertFalse(al.ehInicioOperador('a'));
		assertFalse(al.ehInicioOperador('z'));
		assertFalse(al.ehInicioOperador('A'));
		assertFalse(al.ehInicioOperador('Z'));
		assertFalse(al.ehInicioOperador(')'));

	}

	public void testGetOperador() throws UnknownException {

		Token token = null;

		al = new AnalisadorLexico("");
		token = al.getOperador();
		assertNull(token);

		// Testar Operador seguido por espaço em branco
		al = new AnalisadorLexico("+ ");
		token = al.getOperador();
		assertEquals("+", token.getLexema());
		al = new AnalisadorLexico("- ");
		token = al.getOperador();
		assertEquals("-", token.getLexema());
		al = new AnalisadorLexico("* ");
		token = al.getOperador();
		assertEquals("*", token.getLexema());
		al = new AnalisadorLexico("/ ");
		token = al.getOperador();
		assertEquals("/", token.getLexema());
		al = new AnalisadorLexico("= ");
		token = al.getOperador();
		assertEquals("=", token.getLexema());
		al = new AnalisadorLexico("> ");
		token = al.getOperador();
		assertEquals(">", token.getLexema());
		al = new AnalisadorLexico(">= ");
		token = al.getOperador();
		assertEquals(">=", token.getLexema());
		al = new AnalisadorLexico("< ");
		token = al.getOperador();
		assertEquals("<", token.getLexema());
		al = new AnalisadorLexico("<= ");
		token = al.getOperador();
		assertEquals("<=", token.getLexema());
		al = new AnalisadorLexico("<> ");
		token = al.getOperador();
		assertEquals("<>", token.getLexema());
		al = new AnalisadorLexico(": ");
		token = al.getOperador();
		assertEquals(":", token.getLexema());
		al = new AnalisadorLexico(":= ");
		token = al.getOperador();
		assertEquals(":=", token.getLexema());

		// Testar Operador no fim do fluxo de caracteres
		al = new AnalisadorLexico("+");
		token = al.getOperador();
		assertEquals("+", token.getLexema());
		al = new AnalisadorLexico("-");
		token = al.getOperador();
		assertEquals("-", token.getLexema());
		al = new AnalisadorLexico("*");
		token = al.getOperador();
		assertEquals("*", token.getLexema());
		al = new AnalisadorLexico("/");
		token = al.getOperador();
		assertEquals("/", token.getLexema());
		al = new AnalisadorLexico("=");
		token = al.getOperador();
		assertEquals("=", token.getLexema());
		al = new AnalisadorLexico(">");
		token = al.getOperador();
		assertEquals(">", token.getLexema());
		al = new AnalisadorLexico(">=");
		token = al.getOperador();
		assertEquals(">=", token.getLexema());
		al = new AnalisadorLexico("<");
		token = al.getOperador();
		assertEquals("<", token.getLexema());
		al = new AnalisadorLexico("<=");
		token = al.getOperador();
		assertEquals("<=", token.getLexema());
		al = new AnalisadorLexico("<>");
		token = al.getOperador();
		assertEquals("<>", token.getLexema());
		al = new AnalisadorLexico(":");
		token = al.getOperador();
		assertEquals(":", token.getLexema());
		al = new AnalisadorLexico(":=");
		token = al.getOperador();
		assertEquals(":=", token.getLexema());

		// Testar Operador seguido por qualquer outro caractere válido ('Z')
		al = new AnalisadorLexico("+Z");
		token = al.getOperador();
		assertEquals("+", token.getLexema());
		al = new AnalisadorLexico("-Z");
		token = al.getOperador();
		assertEquals("-", token.getLexema());
		al = new AnalisadorLexico("*Z");
		token = al.getOperador();
		assertEquals("*", token.getLexema());
		al = new AnalisadorLexico("/Z");
		token = al.getOperador();
		assertEquals("/", token.getLexema());
		al = new AnalisadorLexico("=Z");
		token = al.getOperador();
		assertEquals("=", token.getLexema());
		al = new AnalisadorLexico(">Z");
		token = al.getOperador();
		assertEquals(">", token.getLexema());
		al = new AnalisadorLexico(">=Z");
		token = al.getOperador();
		assertEquals(">=", token.getLexema());
		al = new AnalisadorLexico("<Z");
		token = al.getOperador();
		assertEquals("<", token.getLexema());
		al = new AnalisadorLexico("<=Z");
		token = al.getOperador();
		assertEquals("<=", token.getLexema());
		al = new AnalisadorLexico("<>Z");
		token = al.getOperador();
		assertEquals("<>", token.getLexema());
		al = new AnalisadorLexico(":Z");
		token = al.getOperador();
		assertEquals(":", token.getLexema());
		al = new AnalisadorLexico(":=Z");
		token = al.getOperador();
		assertEquals(":=", token.getLexema());
		assertEquals('Z', al.getFluxoDeCaractere().getProxCaractere().charValue());

	}

	public void testGetOperadorComCaracteresInvalidos() throws UnknownException {

		Token token = null;

		// Testar Operador seguido por espaço em branco
		al = new AnalisadorLexico(">" + caracteresInvalidos + "= ");
		try {
			token = al.getOperador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals(">=", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}
		al = new AnalisadorLexico("<" + caracteresInvalidos + "= ");
		try {
			token = al.getOperador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("<=", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}
		al = new AnalisadorLexico("<" + caracteresInvalidos + "> ");
		try {
			token = al.getOperador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("<>", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}
		al = new AnalisadorLexico(":" + caracteresInvalidos + "= ");
		try {
			token = al.getOperador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals(":=", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}

		// Testar Operador no fim do fluxo de caracteres
		al = new AnalisadorLexico(">" + caracteresInvalidos + "=");
		try {
			token = al.getOperador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals(">=", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}
		al = new AnalisadorLexico("<" + caracteresInvalidos + "=");
		try {
			token = al.getOperador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("<=", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}
		al = new AnalisadorLexico("<" + caracteresInvalidos + ">");
		try {
			token = al.getOperador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("<>", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}
		al = new AnalisadorLexico(":" + caracteresInvalidos + "=");
		try {
			token = al.getOperador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals(":=", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}

		// Testar Operador seguido por qualquer outro caractere válido ('Z')
		al = new AnalisadorLexico(">" + caracteresInvalidos + "=Z");
		try {
			token = al.getOperador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals(">=", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}
		al = new AnalisadorLexico("<" + caracteresInvalidos + "=Z");
		try {
			token = al.getOperador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("<=", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}
		al = new AnalisadorLexico("<" + caracteresInvalidos + ">Z");
		try {
			token = al.getOperador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("<>", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}
		al = new AnalisadorLexico(":" + caracteresInvalidos + "=Z");
		try {
			token = al.getOperador();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals(":=", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}
	}

	public void testGetOperadorLinhaEColunaDoToken() throws UnknownException {

		Token token = null;

		al = new AnalisadorLexico(":=");
		token = al.getProxToken();
		assertTrue(token.ehOperador());
		assertEquals(1, token.getLinha());
		assertEquals(1, token.getColuna());

		al = new AnalisadorLexico(" :=");
		token = al.getProxToken();
		assertTrue(token.ehOperador());
		assertEquals(1, token.getLinha());
		assertEquals(2, token.getColuna());

		al = new AnalisadorLexico("\n:=");
		token = al.getProxToken();
		assertTrue(token.ehOperador());
		assertEquals(2, token.getLinha());
		assertEquals(1, token.getColuna());

		al = new AnalisadorLexico("\n :=");
		token = al.getProxToken();
		assertTrue(token.ehOperador());
		assertEquals(2, token.getLinha());
		assertEquals(2, token.getColuna());
	}

	public void testEhInicioParentisador() {

		assertTrue(al.ehInicioParentisador(')'));
		assertTrue(al.ehInicioParentisador('('));
		assertTrue(al.ehInicioParentisador('['));
		assertTrue(al.ehInicioParentisador(']'));
		assertTrue(al.ehInicioParentisador('{'));
		assertTrue(al.ehInicioParentisador('}'));

		assertFalse(al.ehInicioParentisador('+'));
		assertFalse(al.ehInicioParentisador('a'));
		assertFalse(al.ehInicioParentisador('z'));
		assertFalse(al.ehInicioParentisador('A'));
		assertFalse(al.ehInicioParentisador('Z'));
		assertFalse(al.ehInicioParentisador(':'));

	}

	public void testGetParentisador() throws UnknownException {

		Token token = null;

		al = new AnalisadorLexico("");
		token = al.getParentisador();
		assertNull(token);

		// Testar Operador seguido por espaço em branco
		al = new AnalisadorLexico(") ");
		token = al.getParentisador();
		assertEquals(")", token.getLexema());
		al = new AnalisadorLexico("( ");
		token = al.getParentisador();
		assertEquals("(", token.getLexema());
		al = new AnalisadorLexico("[ ");
		token = al.getParentisador();
		assertEquals("[", token.getLexema());
		al = new AnalisadorLexico("] ");
		token = al.getParentisador();
		assertEquals("]", token.getLexema());

		// Testar Operador no fim do fluxo de caracteres
		al = new AnalisadorLexico(")");
		token = al.getParentisador();
		assertEquals(")", token.getLexema());
		al = new AnalisadorLexico("(");
		token = al.getParentisador();
		assertEquals("(", token.getLexema());
		al = new AnalisadorLexico("[");
		token = al.getParentisador();
		assertEquals("[", token.getLexema());
		al = new AnalisadorLexico("]");
		token = al.getParentisador();
		assertEquals("]", token.getLexema());

		// Testar Operador seguido por qualquer outro caractere válido ('Z')
		al = new AnalisadorLexico(")Z");
		token = al.getParentisador();
		assertEquals(")", token.getLexema());
		al = new AnalisadorLexico("(Z");
		token = al.getParentisador();
		assertEquals("(", token.getLexema());
		al = new AnalisadorLexico("[Z");
		token = al.getParentisador();
		assertEquals("[", token.getLexema());
		al = new AnalisadorLexico("]Z");
		token = al.getParentisador();
		assertEquals("]", token.getLexema());
	}

	public void testGetParentisadorComCaracteresInvalidos() throws UnknownException {
		// Nada a fazer, não temos parentisador com mais de um caractere
	}

	public void testGetParentisadorLinhaEColunaDoToken() throws UnknownException {

		Token token = null;

		al = new AnalisadorLexico(")");
		token = al.getProxToken();
		assertTrue(token.ehParentisador());
		assertEquals(1, token.getLinha());
		assertEquals(1, token.getColuna());

		al = new AnalisadorLexico(" )");
		token = al.getProxToken();
		assertTrue(token.ehParentisador());
		assertEquals(1, token.getLinha());
		assertEquals(2, token.getColuna());

		al = new AnalisadorLexico("\n)");
		token = al.getProxToken();
		assertTrue(token.ehParentisador());
		assertEquals(2, token.getLinha());
		assertEquals(1, token.getColuna());

		al = new AnalisadorLexico("\n )");
		token = al.getProxToken();
		assertTrue(token.ehParentisador());
		assertEquals(2, token.getLinha());
		assertEquals(2, token.getColuna());
	}

	public void testEhInicioSinalDePontuacao() {

		assertTrue(al.ehInicioSinalDePontuacao(';'));

		assertFalse(al.ehInicioSinalDePontuacao(')'));
		assertFalse(al.ehInicioSinalDePontuacao('a'));
		assertFalse(al.ehInicioSinalDePontuacao('z'));
		assertFalse(al.ehInicioSinalDePontuacao('A'));
		assertFalse(al.ehInicioSinalDePontuacao('Z'));
		assertFalse(al.ehInicioSinalDePontuacao('<'));
	}

	public void testGetSinalDePontuacao() throws UnknownException {

		Token token = null;

		al = new AnalisadorLexico("");
		token = al.getSinalDePontuacao();
		assertNull(token);

		// Testar Operador seguido por espaço em branco
		al = new AnalisadorLexico("; ");
		token = al.getSinalDePontuacao();
		assertEquals(";", token.getLexema());

		// Testar Operador no fim do fluxo de caracteres
		al = new AnalisadorLexico(";");
		token = al.getSinalDePontuacao();
		assertEquals(";", token.getLexema());

		// Testar Operador seguido por qualquer outro caractere válido ('Z')
		al = new AnalisadorLexico(";Z");
		token = al.getSinalDePontuacao();
		assertEquals(";", token.getLexema());
	}

	public void testGetSinalDePontuacaoComCaracteresInvalidos() throws UnknownException {
		// Nada a fazer, não temos parentisador com mais de um caractere
	}

	public void testGetSinalDePontuacaoLinhaEColunaDoToken() throws UnknownException {

		Token token = null;

		al = new AnalisadorLexico(";");
		token = al.getProxToken();
		assertTrue(token.ehSinalDePontuacao());
		assertEquals(1, token.getLinha());
		assertEquals(1, token.getColuna());

		al = new AnalisadorLexico(" ;");
		token = al.getProxToken();
		assertTrue(token.ehSinalDePontuacao());
		assertEquals(1, token.getLinha());
		assertEquals(2, token.getColuna());

		al = new AnalisadorLexico("\n;");
		token = al.getProxToken();
		assertTrue(token.ehSinalDePontuacao());
		assertEquals(2, token.getLinha());
		assertEquals(1, token.getColuna());

		al = new AnalisadorLexico("\n ;");
		token = al.getProxToken();
		assertTrue(token.ehSinalDePontuacao());
		assertEquals(2, token.getLinha());
		assertEquals(2, token.getColuna());
	}

	public void testEhInicioCadeia() {

		assertTrue(al.ehInicioCadeia('\''));

		assertFalse(al.ehInicioCadeia(')'));
		assertFalse(al.ehInicioCadeia('a'));
		assertFalse(al.ehInicioCadeia('z'));
		assertFalse(al.ehInicioCadeia('A'));
		assertFalse(al.ehInicioCadeia('Z'));
		assertFalse(al.ehInicioCadeia('<'));

	}

	public void testGetCadeia() throws UnknownException {

		Token token = null;

		al = new AnalisadorLexico("");
		token = al.getCadeia();
		assertNull(token);

		// Testar Cadeia seguido por espaço em branco
		al = new AnalisadorLexico("'' ");
		token = al.getCadeia();
		assertEquals("''", token.getLexema());
		al = new AnalisadorLexico("'0-9 \r\t\n\fa-zA-Z_+-*/=:><)([];' ");
		token = al.getCadeia();
		assertEquals("'0-9 \r\t\n\fa-zA-Z_+-*/=:><)([];'", token.getLexema());

		// Testar Cadeia no fim do fluxo de caracteres
		al = new AnalisadorLexico("''");
		token = al.getCadeia();
		assertEquals("''", token.getLexema());
		al = new AnalisadorLexico("'0-9 \r\t\n\fa-zA-Z_+-*/=:><)([];'");
		token = al.getCadeia();
		assertEquals("'0-9 \r\t\n\fa-zA-Z_+-*/=:><)([];'", token.getLexema());

		// Testar Cadeia seguido por qualquer outro caractere válido ('Z')
		al = new AnalisadorLexico("''Z");
		token = al.getCadeia();
		assertEquals("''", token.getLexema());
		al = new AnalisadorLexico("'0-9 \r\t\n\fa-zA-Z_+-*/=:><)([];'Z");
		token = al.getCadeia();
		assertEquals("'0-9 \r\t\n\fa-zA-Z_+-*/=:><)([];'", token.getLexema());

	}

	/**
	 * Tenta identificar uma cadeia com caracteres inválidos dentro da cadeia.
	 * Deve ser possível sem problemas.
	 * 
	 * @throws UnknownException
	 */
	public void testGetCadeiaComCaracteresInvalidos() throws UnknownException {

		Token token = null;

		// Testar Cadeia seguido por espaço em branco e com caracteres inválidos
		// dentro da cadeia
		al = new AnalisadorLexico("'0-9 \r\t\n\fa" + caracteresInvalidos + "-zA-Z_+-*/=:><)([];' ");
		token = al.getCadeia();
		assertEquals("'0-9 \r\t\n\fa" + caracteresInvalidos + "-zA-Z_+-*/=:><)([];'", token.getLexema());

		// Testar Cadeia no fim do fluxo de caracteres e com caracteres
		// inválidos dentro da cadeia
		al = new AnalisadorLexico("'0-9 \r\t\n\fa" + caracteresInvalidos + "-zA-Z_+-*/=:><)([];'");
		token = al.getCadeia();
		assertEquals("'0-9 \r\t\n\fa" + caracteresInvalidos + "-zA-Z_+-*/=:><)([];'", token.getLexema());

		// Testar Cadeia seguido por qualquer outro caractere válido ('Z') e com
		// caracteres inválidos dentro da cadeia
		al = new AnalisadorLexico("'0-9 \r\t\n\fa" + caracteresInvalidos + "-zA-Z_+-*/=:><)([];'Z");
		token = al.getCadeia();
		assertEquals("'0-9 \r\t\n\fa" + caracteresInvalidos + "-zA-Z_+-*/=:><)([];'", token.getLexema());

	}

	public void testGetCadeiaLinhaEColunaDoToken() throws UnknownException {

		Token token = null;

		al = new AnalisadorLexico("''");
		token = al.getProxToken();
		assertTrue(token.ehCadeia());
		assertEquals(1, token.getLinha());
		assertEquals(1, token.getColuna());

		al = new AnalisadorLexico(" ''");
		token = al.getProxToken();
		assertTrue(token.ehCadeia());
		assertEquals(1, token.getLinha());
		assertEquals(2, token.getColuna());

		al = new AnalisadorLexico("\n''");
		token = al.getProxToken();
		assertTrue(token.ehCadeia());
		assertEquals(2, token.getLinha());
		assertEquals(1, token.getColuna());

		al = new AnalisadorLexico("\n ''");
		token = al.getProxToken();
		assertTrue(token.ehCadeia());
		assertEquals(2, token.getLinha());
		assertEquals(2, token.getColuna());
	}

	public void testEhInicioNumero() {

		for (char caractere = '0'; caractere < '9'; caractere++) {
			assertTrue(al.ehInicioNumero(caractere));
		}

		assertFalse(al.ehInicioNumero(')'));
		assertFalse(al.ehInicioNumero('a'));
		assertFalse(al.ehInicioNumero('z'));
		assertFalse(al.ehInicioNumero('A'));
		assertFalse(al.ehInicioNumero('Z'));
		assertFalse(al.ehInicioNumero('<'));
	}

	public void testGetNumero() throws UnknownException {

		Token token = null;

		al = new AnalisadorLexico("");
		token = al.getNumero();
		assertNull(token);

		// Testar Cadeia seguido por espaço em branco
		al = new AnalisadorLexico("012345 ");
		token = al.getNumero();
		assertEquals("012345", token.getLexema());

		// Testar Cadeia no fim do fluxo de caracteres
		al = new AnalisadorLexico("012345");
		token = al.getNumero();
		assertEquals("012345", token.getLexema());

		// Testar Cadeia seguido por qualquer outro caractere válido ('Z')
		al = new AnalisadorLexico("012345Z");
		token = al.getNumero();
		assertEquals("012345", token.getLexema());
	}

	public void testGetNumeroComCaracteresInvalidos() throws UnknownException {

		Token token = null;

		// Testar Cadeia seguido por espaço em branco
		al = new AnalisadorLexico("0" + caracteresInvalidos + "12345 ");
		try {
			token = al.getNumero();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("012345", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}

		// Testar Cadeia no fim do fluxo de caracteres
		al = new AnalisadorLexico("0" + caracteresInvalidos + "12345");
		try {
			token = al.getNumero();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("012345", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}

		// Testar Cadeia seguido por qualquer outro caractere válido ('Z')
		al = new AnalisadorLexico("0" + caracteresInvalidos + "12345Z");
		try {
			token = al.getNumero();
			fail("Erro! Era pra ter sido lançada uma exceção de Caractere Inválido!");
			assertEquals("012345", token.getLexema());
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(caracteresInvalidos.charAt(0), e.getCaractere().charValue());
		}
	}

	public void testGetNumeroLinhaEColunaDoToken() throws UnknownException {

		Token token = null;

		al = new AnalisadorLexico("0");
		token = al.getProxToken();
		assertTrue(token.ehNumero());
		assertEquals(1, token.getLinha());
		assertEquals(1, token.getColuna());

		al = new AnalisadorLexico(" 0");
		token = al.getProxToken();
		assertTrue(token.ehNumero());
		assertEquals(1, token.getLinha());
		assertEquals(2, token.getColuna());

		al = new AnalisadorLexico("\n0");
		token = al.getProxToken();
		assertTrue(token.ehNumero());
		assertEquals(2, token.getLinha());
		assertEquals(1, token.getColuna());

		al = new AnalisadorLexico("\n 0");
		token = al.getProxToken();
		assertTrue(token.ehNumero());
		assertEquals(2, token.getLinha());
		assertEquals(2, token.getColuna());
	}

	public void testLeituraDeCaractereInvalido() throws UnknownException, IOException {

		String codigoFonte = caracteresInvalidos;
		char[] caracteresInvalidos = codigoFonte.toCharArray();
		for (int i = 0; i < caracteresInvalidos.length; i++) {

			assertFalse(al.ehCaractereValido(caracteresInvalidos[i]));

		}

	}

	public void testRangeDoTokenNum() throws UnknownException {// -32768, 32767

		al = new AnalisadorLexico("32767");
		try {
			al.getNumero();
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			fail("Erro! Esperado aceitar o número máximo permitido 32767");
		}

		al = new AnalisadorLexico("-32768");
		try {
			al.getNumero();
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			fail("Erro! Esperado aceitar o número mínimo permitido -32768");
		}

		al = new AnalisadorLexico("32768");
		try {
			al.getNumero();
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			fail("Erro! O range do número só deve ser verificado no Analisador Semântico");
		}

		al = new AnalisadorLexico("-32769");
		try {
			al.getNumero();
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			fail("Erro! O range do número só deve ser verificado no Analisador Semântico");
		}
	}

	public void testTamMaximoDoTokenIdentificador() throws UnknownException {// 50
		StringBuilder sb = new StringBuilder();

		for (int i = 0; i < AnalisadorLexico.TAM_MAXIMO_IDENTIFICADOR; i++) {
			sb.append("a");
		}

		al = new AnalisadorLexico(sb.toString());
		try {
			al.getIdentificador();
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			fail("Erro! Era pra ser aceito IDENTIFICADOR com o tamanho igual ao máximo permitido");
		}

		sb.append("a");

		al = new AnalisadorLexico(sb.toString());
		try {
			al.getIdentificador();
			fail("Erro! Não era pra ser aceito IDENTIFICADOR com o tamanho maior que o máximo permitido");
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(sb.toString(), e.getToken().getLexema());
		}
	}

	public void testTamMaximoDoTokenCadeia() throws UnknownException {// 1024
		StringBuilder sb = null;

		sb = new StringBuilder();
		sb.append("'");
		for (int i = 0; i < AnalisadorLexico.TAM_MAXIMO_CADEIA; i++) {
			sb.append("a");
		}
		sb.append("'");

		al = new AnalisadorLexico(sb.toString());
		try {
			al.getCadeia();
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			fail("Erro! Era pra ser aceito CADEIA com o tamanho igual ao máximo permitido");
		}

		sb = new StringBuilder();
		sb.append("'");
		for (int i = 0; i <= AnalisadorLexico.TAM_MAXIMO_CADEIA; i++) {
			sb.append("a");
		}
		sb.append("'");

		al = new AnalisadorLexico(sb.toString());
		try {
			al.getCadeia();
			fail("Erro! Não era pra ser aceito CADEIA com o tamanho maior que o máximo permitido");
		} catch (AnalisadorLexicoUnknownRuntimeException e) {
			assertEquals(sb.toString(), e.getToken().getLexema());
		}

	}
}
